package com.example.pt.service.impl;

import com.example.pt.entity.Invitation;
import com.example.pt.entity.User;
import com.example.pt.entity.UserLevel;
import com.example.pt.entity.UserTransferStats;
import com.example.pt.mapper.UserMapper;
import com.example.pt.mapper.UserTransferStatsMapper;
import com.example.pt.repository.InvitationRepositories;
import com.example.pt.repository.UserRepositories;
import com.example.pt.service.UserLevelService;
import com.example.pt.service.UserSeedStatsService;
import com.example.pt.service.UserTransferStatsService;
import com.example.pt.utils.UserToUserESUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class UserLevelServiceImpl implements UserLevelService {

    private static final Logger logger = LoggerFactory.getLogger(UserLevelServiceImpl.class);
    
    // 邀请码兑换所需积分
    private static final int INVITATION_POINTS_COST = 500;
    
    // 邀请新用户获得的积分奖励
    private static final int INVITATION_POINTS_REWARD = 200;
    
    // 新用户使用邀请码获得的积分
    private static final int NEW_USER_INVITATION_POINTS = 100;
    
    // 邀请码有效期(天)
    private static final int INVITATION_VALIDITY_DAYS = 30;

    @Autowired
    private UserRepositories userRepositories;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private UserTransferStatsService userTransferStatsService;
    
    @Autowired
    private UserTransferStatsMapper userTransferStatsMapper;
    
    @Autowired
    private UserSeedStatsService userSeedStatsService;
    
    @Autowired
    private InvitationRepositories invitationRepositories;

    @Autowired
    private UserToUserESUtils userToUserESUtils;

    @Override
    public int calculateUserPoints(Integer userId) {
        if (userId == null) {
            return 0;
        }
        
        // 直接使用Mapper查询用户的传输统计数据
        List<UserTransferStats> transferStatsList = userTransferStatsMapper.selectList(
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<UserTransferStats>()
                .eq(UserTransferStats::getUserId, userId)
        );
        
        // 计算上传量(单位:GB)和下载量(单位:GB)
        long totalUploaded = 0;
        long totalDownloaded = 0;
        
        for (UserTransferStats stats : transferStatsList) {
            totalUploaded += stats.getUploaded();
            totalDownloaded += stats.getDownloaded();
        }
        
        // 转换为GB并向下取整
        int uploadedGB = (int) (totalUploaded / (1024 * 1024 * 1024));
        int downloadedGB = (int) (totalDownloaded / (1024 * 1024 * 1024));
        
        // 获取保种积分
        int seedPoints = calculateSeedPoints(userId);
        
        // 获取用户
        User user = userRepositories.findByUid(userId);
        
        // 初始积分(可能为0)
        int initialPoints = (user != null) ? user.getPoints() : 0;
        
        // 计算总积分: 上传量*5 + 下载量*2 + 保种积分*3 + 初始积分
        return uploadedGB * 5 + downloadedGB * 2 + seedPoints * 3 + initialPoints;
    }

    @Override
    public int calculateSeedPoints(Integer userId) {
        return userSeedStatsService.getTotalSeedPoints(userId);
    }

    @Override
    @Transactional
    public UserLevel updateUserLevel(Integer userId) {
        if (userId == null) {
            return UserLevel.REGISTERED;
        }
        
        // 获取用户
        User user = userRepositories.findByUid(userId);
        if (user == null) {
            return UserLevel.REGISTERED;
        }
        
        // 计算用户积分
        int points = calculateUserPoints(userId);
        
        // 获取对应等级
        UserLevel level = UserLevel.getLevelByPoints(points);
        
        // 更新用户积分和等级
        user.setPoints(points);
        user.setLevel(level.getId());
        userRepositories.save(user);

        userToUserESUtils.syncToES(user);
        
        return level;
    }

    @Override
    public UserLevel getUserLevel(Integer userId) {
        if (userId == null) {
            return UserLevel.REGISTERED;
        }
        
        User user = userRepositories.findByUid(userId);
        if (user == null) {
            return UserLevel.REGISTERED;
        }
        
        return UserLevel.getLevelById(user.getLevel());
    }

    @Override
    @Transactional
    public boolean rewardNewUserWithInvitation(Integer userId, String invitationCode) {
        if (userId == null || invitationCode == null || invitationCode.isEmpty()) {
            return false;
        }
        
        // 查找邀请码
        Invitation invitation = invitationRepositories.findByInvitationCode(invitationCode);
        if (invitation == null || !invitation.isValid()) {
            return false;
        }
        
        // 获取新用户
        User newUser = userRepositories.findByUid(userId);
        if (newUser == null) {
            return false;
        }
        
        // 设置新用户积分
        newUser.setPoints(newUser.getPoints() + NEW_USER_INVITATION_POINTS);
        userRepositories.save(newUser);
        
        // 使用邀请码并更新状态
        boolean useSuccess = invitation.use();
        if (!useSuccess) {
            return false;
        }
        
        // 更新邀请码的最后使用者
        invitation.setUsedBy(userId);
        
        // 如果是首次使用，将状态更新为已使用状态
        if (invitation.getStatus() == 0) {
            invitation.setStatus(1);
        }
        
        invitationRepositories.save(invitation);
        
        // 更新邀请人积分
        updateInviterPoints(invitationCode);
        
        return true;
    }

    @Override
    @Transactional
    public String exchangeInvitationCode(Integer userId) throws Exception {
        if (userId == null) {
            throw new Exception("用户ID不能为空");
        }
        
        // 获取用户
        User user = userRepositories.findByUid(userId);
        if (user == null) {
            throw new Exception("用户不存在");
        }
        
        // 检查用户等级
        UserLevel userLevel = UserLevel.getLevelById(user.getLevel());
        if (!userLevel.canExchangeInvitation()) {
            throw new Exception("用户等级不足，无法兑换邀请码");
        }
        
        // 检查用户积分
        if (user.getPoints() < INVITATION_POINTS_COST) {
            throw new Exception("积分不足，无法兑换邀请码");
        }
        
        // 扣除积分
        user.setPoints(user.getPoints() - INVITATION_POINTS_COST);
        userRepositories.save(user);
        
        // 生成邀请码
        String invitationCode = generateInvitationCode();
        
        // 创建邀请记录
        Invitation invitation = new Invitation();
        invitation.setUid(userId);
        invitation.setInvitationCode(invitationCode);
        invitation.setCreateTime(new Date());
        
        // 设置过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, INVITATION_VALIDITY_DAYS);
        invitation.setExpireTime(calendar.getTime());
        
        invitation.setStatus(0); // 未使用
        invitationRepositories.save(invitation);
        
        return invitationCode;
    }

    @Override
    @Transactional
    public boolean updateInviterPoints(String invitationCode) {
        if (invitationCode == null || invitationCode.isEmpty()) {
            return false;
        }
        
        Invitation invitation = invitationRepositories.findByInvitationCode(invitationCode);
        if (invitation == null || invitation.getStatus() != 1) { // 确保邀请码已被使用
            return false;
        }
        
        // 获取邀请人
        User inviter = userRepositories.findByUid(invitation.getUid());
        if (inviter == null) {
            return false;
        }
        
        // 更新邀请人积分
        inviter.setPoints(inviter.getPoints() + INVITATION_POINTS_REWARD);
        userRepositories.save(inviter);
        
        // 更新邀请人等级
        updateUserLevel(inviter.getUid());
        
        return true;
    }
    
    /**
     * 生成唯一的邀请码
     * @return 邀请码
     */
    private String generateInvitationCode() {
        return UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
} 